package moodish.client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Date;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import moodish.comm.ClientComm;
import moodish.comm.MoodishClientComm;
import moodish.comm.MoodishClientSideMessage;

/**
 * 
 * ClientGUI is the GUI interface that allows a user to: 
 * - connect and disconnect from Moodish servers;
 * - display messages received from friends;
 * - browse through his/her own moods and the moods from his/her friends;
 * - see the list of friends currently connected;
 * - see the list of non friends online users;
 * - friend or unfriend a specific user;
 * - choose a mood.
 * 
 * @author es1-2013-group2
 *
 */
public class ClientGUI extends JFrame implements MoodishClient{

	private static MoodishClientComm clientComm;
	private String nickname;
	private User user;
	private Talk talk;
	private JPanel westPanel;
	private NorthPanel northPanel;
	private OnlineUsersPanel onlineUsersPanel;
	private FriendsPanel friendsPanel;
	private UserPanel userPanel;

	/**
	 * The Constructor allows the user to set a nickname and initializes all the panels which configure the GUI, creates the main window 
	 */
	public ClientGUI(){
		nickname = JOptionPane.showInputDialog("Nickname");
		user = new User(nickname, Mood.Happy);

		Container container = getContentPane();
		container.setLayout(new BorderLayout());
		((JComponent) container).setBorder(BorderFactory.createLineBorder(Color.BLACK, 10));
		container.setBackground(Color.BLACK);

		talk = new Talk();
		JScrollPane talkScrollPane = new JScrollPane(talk);
		Rectangle visibleRect = talkScrollPane.getVisibleRect();
		visibleRect.y = talkScrollPane.getHeight() - visibleRect.height;
		talkScrollPane.scrollRectToVisible(visibleRect);
		this.add(talkScrollPane, BorderLayout.CENTER);
		talkScrollPane = new JScrollPane(talk);
		this.getContentPane().add(talkScrollPane, BorderLayout.CENTER);

		westPanel = new JPanel();
		userPanel = new UserPanel(this,user, talk);
		userPanel.setPreferredSize(new Dimension(westPanel.getSize().width, 90));
		friendsPanel = new FriendsPanel(this);	

		westPanel.setBorder(BorderFactory.createEmptyBorder());
		westPanel.setLayout(new BorderLayout());
		westPanel.add(userPanel, BorderLayout.NORTH);
		westPanel.add(friendsPanel, BorderLayout.CENTER);
		this.getContentPane().add(westPanel, BorderLayout.WEST);

		northPanel = new NorthPanel(this);
		this.add(northPanel, BorderLayout.NORTH);

		onlineUsersPanel = new OnlineUsersPanel(this);
		this.add(onlineUsersPanel, BorderLayout.EAST);

		JLabel bottomLabel = new JLabel();
		bottomLabel.setBackground(Color.BLACK);
		bottomLabel.setPreferredSize(new Dimension(900,20));
		this.add(bottomLabel, BorderLayout.SOUTH);

		this.setTitle("MOODISH - " + user.getNickname());
		//this.setSize(900, 600);
		this.getContentPane().setPreferredSize(new Dimension(920,620));
		this.setResizable(false);	

		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent event) {
				int confirm = JOptionPane.showOptionDialog(new JFrame(),
						"Are You sure to close Moodish?",
						"Exit Confirmation", JOptionPane.YES_NO_OPTION,
						JOptionPane.QUESTION_MESSAGE, null, null, null);
				if (confirm == JOptionPane.YES_OPTION) {
					if(user.isConnected())
						disconnect(1);
					System.exit(1);
				}
			}
		});



	}

	public User getUser(){
		return user;
	}


	/**
	 * 
	 * Add the user to the friendsPanel.
	 * Add the user (new friend) to the friends User.
	 * Send the request to be friend of another client to the clientComm.
	 * 
	 * @param user Friend User.
	 */
	public void addFriend(User user){
		friendsPanel.addFriend(user);
		user.addFriend(user);
		clientComm.friendship(user.getNickname());
	}

	/**
	 * Remove friend from the Users friends. 
	 * Send the request to unfriend a client to the clienComm.
	 * 
	 * @param user Friend User.
	 */
	public void removeFriend(User user){
		user.removeFriend(user);
		clientComm.unfriendship(user.getNickname());
	}

	/**
	 * Add user to the onlineUsersPanel.
	 * 
	 * @param user OnlineUser.
	 */
	public void addOnlineUser(User user){
		onlineUsersPanel.addUser(user);
		onlineUsersPanel.repaint();

	}

	/**
	 * Check if currently client is connected to a host through clientComm.
	 * 
	 * @return True if clientComm is connected.
	 */
	public boolean isConnected(){
		return clientComm.isConnected();
	}

	/**
	 * Establish a connection to a Moodish server through clientComm.
	 * Enables the MoodButton. User has the possibility to change his/her mood.
	 * 
	 * @param host String with the host.
	 */
	public void connect(String host){
		try {
			user.connect();
			clientComm.connect(host, user.getNickname());
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		userPanel.enableMoodButton();
		System.out.println("EU " + nickname + " conectei-me");



	}

	/**
	 * 
	 * The parameter n defines if the client is already disconnected or not:
	 * - If n is equal to 1 it disconnects from a Moodish server through clientComm;
	 * - If not, it's not necessary to disconnect.
	 * All the operations that deal with the disconnetion are done here:
	 * - disable the Moodbutton;
	 * - remove all the friends from the FriendsPanel; 
	 * - remove all the users from the onlineUsersPanel;
	 * - set the connection status button to red.
	 * 
	 * @param n Integer 1 to disconnect.
	 */
	public void disconnect(int n){

		if(n == 1)
			clientComm.disconnect();

		user.disconnect();
		userPanel.disableMoodButton();
		user.removeAllFriends();
		friendsPanel.removeAllFriends();
		northPanel.setButtonRed();
		onlineUsersPanel.removeAllUsers();
	}

	/**
	 * 
	 * Send a Moodish message from this client to the server through clientComm.
	 * 
	 * @param message String with the message.
	 */
	public void sendMoodishMessage(String message){
		clientComm.sendMoodishMessage(message);
	}

	/* (non-Javadoc)
	 * @see moodish.client.MoodishClient#start(moodish.comm.ClientComm)
	 */
	@Override
	public void start(ClientComm clientComm) {
		this.clientComm = (MoodishClientComm) clientComm;
		this.pack();
		this.setLocationRelativeTo(null);
		this.setVisible(true);

		talk.addMessage("\n   Welcome to Moodish! \n");
		new MsgReceiverThread().start();

	}

	private class MsgReceiverThread extends Thread{		
		public void run(){
			System.out.println("no run do client");
			boolean interrupt = false;

			while (!interrupt){
				MoodishClientSideMessage message = null;
				if (clientComm.hasNextMessage()){
					message = (MoodishClientSideMessage) clientComm.getNextMessage();

					if(message==null)
						interrupt=true;

					System.out.println("Eu " + nickname + " ClientGUI recebi mensagem: " + message.getPayload() + message.getSendersNickname());

					switch (message.getType()) {
					case MOODISH_MESSAGE:
						System.out.println("mensagem do tipo : " + message.getType());
						Date date = new Date();
						talk.addMoodMessage(date,message.getSendersNickname(),message.getPayload());
						friendsPanel.setFriendMood(message.getSendersNickname(), message.getPayload());
						break;
					case CONNECTED:
						System.out.println("mensagem do tipo : " + message.getType());
						User newUser = new User(message.getPayload(), Mood.Happy);
						onlineUsersPanel.addUser(newUser);
						break;
					case DISCONNECTED:
						if(message.getPayload().equals(nickname)){
							user.removeFriend(message.getPayload());	
							disconnect(1);
							friendsPanel.removeFriend(message.getPayload());									
						}
						else {
							System.out.println("mensagem do tipo : " + message.getType());
							onlineUsersPanel.removeUser(message.getPayload());
							user.removeFriend(message.getPayload());
							friendsPanel.removeFriend(message.getPayload());
						}


						break;
					case ERROR:
						System.out.println("mensagem do tipo : " + message.getType());
						JOptionPane.showMessageDialog(new JFrame(), message.getPayload(), "Warning", JOptionPane.WARNING_MESSAGE);
						break;
					}
				}
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			JOptionPane.showMessageDialog(new JFrame(),"Disconnected from server.", "Error",
					JOptionPane.ERROR_MESSAGE);

			disconnect(0);


		}



	}



}




